#include "stdafx.h"
#include "memstatics.h"

typedef struct{
	void*(*threadfunc)(void*);
	char threadname[32];
	void* param;
}fakeparam;
typedef struct meminfo_t{
	struct meminfo_t* next;
	char funcname[32];
	void* ptr;
	int size;
}MEMINFO;
typedef struct threadmeminfo_t{
	char threadname[32];
	pthread_t threadid;
	MEMINFO* pmeminfo;
	struct threadmeminfo_t* next;
}THREADMEMINFO;

THREADMEMINFO* g_threadmeminfo;
void NULLEXIT(void* ptr,const char* info)
{
	if(NULL==ptr)
	{
		fprintf(stderr,"NULL find and exit!:%s\n",info);
		exit(0);
	}
}
void memstatics_init()
{
	g_threadmeminfo=calloc(1,sizeof(THREADMEMINFO));
	NULLEXIT(g_threadmeminfo,"memstatics_init,calloc failed!\n");
	g_threadmeminfo->threadid=pthread_self();
	strncpy(g_threadmeminfo->threadname,"mainthread",31);
}
void memstatics_addthread(pthread_t threadid,const char* threadname)
{
	THREADMEMINFO* tmpinfo=g_threadmeminfo;
	while(NULL!=tmpinfo->next)
		tmpinfo=tmpinfo->next;
	THREADMEMINFO* theinfo=calloc(1,sizeof(THREADMEMINFO));
	NULLEXIT(theinfo,"fail to calloc in memstatics_addthread!\n");
	strncpy(theinfo->threadname,threadname,31);
	theinfo->threadid=threadid;
	tmpinfo->next=theinfo;
}
void memstatics_addmem(const char* funcname,void* ptr,int size)
{
	THREADMEMINFO* tmpinfo=g_threadmeminfo;
	while(tmpinfo!=NULL&&pthread_self()!=tmpinfo->threadid)
		tmpinfo=tmpinfo->next;
	NULLEXIT(tmpinfo,"fail to find threadid");
	MEMINFO* tmpmeminfo=tmpinfo->pmeminfo;
	while(tmpmeminfo->next!=NULL)
		tmpmeminfo=tmpmeminfo->next;

	MEMINFO* tobeadd=calloc(1,sizeof(MEMINFO));
	NULLEXIT(tobeadd,"fail to calloc tobeadd!\n");

	strncpy(tobeadd->funcname,funcname,31);
	tobeadd->ptr=ptr;
	tobeadd->size=size;
	tmpmeminfo->next=tobeadd;
}
void memstatics_delmem(void* ptr)
{
	THREADMEMINFO* tmpinfo=g_threadmeminfo;

	while(tmpinfo!=NULL&&pthread_self()!=tmpinfo->threadid)
		tmpinfo=tmpinfo->next;
	NULLEXIT(tmpinfo,"fail to find threadid");
	MEMINFO* tmpmeminfo=tmpinfo->pmeminfo;
	MEMINFO* pretmpmeminfo=tmpinfo->pmeminfo;
	while(tmpmeminfo!=NULL)
	{
		if(tmpmeminfo->ptr==ptr)
			break;
		pretmpmeminfo=tmpmeminfo;
		tmpmeminfo=tmpmeminfo->next;
	}
	NULLEXIT(tmpmeminfo,"fail to find ptr in the calloc thread!\n");

	MEMINFO* tobedel=tmpmeminfo->next;
	if(NULL==tobedel)
	{
		free(tmpmeminfo);
		if(tmpmeminfo==pretmpmeminfo)
		{
			tmpinfo->pmeminfo=NULL;
		}
		else
		{
			pretmpmeminfo->next=NULL;
		}
	}
	else
	{
		memcpy(tmpmeminfo,tobedel,sizeof(MEMINFO));
		free(tobedel);
	}
}

void* fakefunc(void*param)
{
	fakeparam* fake=(fakeparam*)param;
	memstatics_addthread(pthread_self(),fake->threadname);	
	(*fake->threadfunc)(fake->param);
	free(fake);
	return NULL;
}
BOOL PTHREAD_CREATE(pthread_t* pthreadid,char* threadname,void*(*threadfunc)(void*),void* param)
{
	fakeparam *fake=malloc(sizeof(fakeparam));
	fake->param=param;
	fake->threadfunc=threadfunc;
	strncpy(fake->threadname,threadname,31);
	return pthread_create(pthreadid,0,fakefunc,param);
}

